/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package submarines;

import submarines.notices.*;
import submarines.ui.ConsoleUi;
import java.util.LinkedList;
import java.util.List;
import SubmarinesBindings.*;
import javax.xml.bind.*;
import submarines.ui.Ui;

/**
 *
 * @author sshiran
 */
public class HumanPlayer extends Player{
    Board lastSeen;
    
    public HumanPlayer(String userName, int userScore)
    {
        super(userName, userScore);
        //this.fillBoard();
        lastSeen = myBoard;
        setType(Config.HUMAN_PLAYER);
    }
    
    //for web use
     public HumanPlayer()
    {
        super("", 0);
        setType(Config.HUMAN_PLAYER);
        lastSeen = myBoard;
    }
     
     //for web use
    public HumanPlayer(String userName)
    {
        super(userName, 0);
        setType(Config.HUMAN_PLAYER);
        lastSeen = myBoard;
    }
          
    public HumanPlayer(String name, List<SubmarinesBindings.Boat> xmlBoats, SubmarinesBindings.Board b) throws JAXBException {
        super(name, xmlBoats, b);
        pType = Config.HUMAN_PLAYER;
        lastSeen = myBoard;
    }
   
    @Override
     void reInitiate() 
    {
        super.reInitiate();
       lastSeen = myBoard;
    }
    
   @Override
    public  void fillBoard()
    {
        int minRow;
        int maxRow;
        int minCol;
        int maxCol;
        int i,j;    
        for (i = Config.SUBMARINES.length; i >=1 ; i--) {
            j = Config.SUBMARINES[i-1];
            while (j > 0) {
                
                
                int direction = Main.userInterface.getSubmarineDirection(i);
                if (direction == 1)
                {
                    minRow = 0;
                    maxRow = Config.BOARD_SIZE - 1;
                    minCol = 0;
                    maxCol = Config.BOARD_SIZE - i;
                    
                }
                else
                {
                    minCol = 0;
                    maxCol = Config.BOARD_SIZE - 1;
                    minRow = 0;
                    maxRow = Config.BOARD_SIZE - i;
                }
                
                int row = Main.userInterface.getSubmarineRow(i, minRow, maxRow);
                int col = Main.userInterface.getSubmarineCol(i, minCol, maxCol);
                boolean success = myBoard.insertShip(row, col, i, direction);
                if (success) {
                    j--;
                } else {
                    Main.userInterface.printAlert("Submarine was placed in an invalid location (Size: " + i +")");
                }
                Main.userInterface.clearScreen();
                Main.userInterface.printBoard(myBoard);
            }
        }
    }

    public  void fillBoard(int direction, int row, int col) //for web use
    {
        int minRow;
        int maxRow;
        int minCol;
        int maxCol;
        int i,j;    
        for (i = Config.SUBMARINES.length; i >=1 ; i--) {
            j = Config.SUBMARINES[i-1];
            while (j > 0) {
                
                
                //int direction = Main.userInterface.getSubmarineDirection(i);
                if (direction == 1)
                {
                    minRow = 0;
                    maxRow = Config.BOARD_SIZE - 1;
                    minCol = 0;
                    maxCol = Config.BOARD_SIZE - i;
                    
                }
                else
                {
                    minCol = 0;
                    maxCol = Config.BOARD_SIZE - 1;
                    minRow = 0;
                    maxRow = Config.BOARD_SIZE - i;
                }
                
                //int row = Main.userInterface.getSubmarineRow(i, minRow, maxRow);
                //int col = Main.userInterface.getSubmarineCol(i, minCol, maxCol);
                boolean success = myBoard.insertShip(row, col, i, direction);
                if (success) {
                    j--;
                } else {
                    Main.userInterface.printAlert("Submarine was placed in an invalid location (Size: " + i +")");
                }
                Main.userInterface.clearScreen();
                Main.userInterface.printBoard(myBoard);
            }
        }
    }
   
    @Override
    public void notifyPlayerGotHit(Notice currNotice) {
        super.notifyPlayerGotHit(currNotice); //notify this player that another player got hit
    }
    
    @Override
    public void notifyPlayerSubmarineSunk(Notice currNotice) {
        super.notifyPlayerSubmarineSunk(currNotice);//notify this player that another player submatine sunk 
    }
    
    @Override
    public void notifyPlayerQuit(Notice currNotice) {
        super.notifyPlayerQuit(currNotice);//notify this player that another player quit 
    }
    
    @Override
    public void notifyPlayerGotLucky(Notice currNotice) {
        super.notifyPlayerGotLucky(currNotice);//notify this player that another player got luck and his submarined didn't got hit 
    }

    
    @Override
    public boolean playTurn() {
        readNotices();
        TurnManager.turnAction act;
        boolean played = false;
        Player t = null;
        String target = "";
        
        while (!played) {
            Main.userInterface.printBoard(lastSeen);
            act = Main.userInterface.getPlayersNextMove();
            
            if (act == TurnManager.turnAction.QUIT_GAME)
                return true;
            
            LinkedList<String> names = new LinkedList<String>();
            for (int i = 0; i < Main.pManager.numPlayersLeft(); i++) {
                Player tmp = Main.pManager.getNextPlayer();
                if (!tmp.getName().equals(getName())) {
                    names.add(tmp.getName());
                }
            }

            if (Main.pManager.numPlayersLeft() == 2) {
                Player tmp = Main.pManager.getNextPlayer();
                target = tmp.getName();
                tmp = Main.pManager.getNextPlayer();
                t = Main.pManager.getPlayerByName(target);
            } else {
                target = Main.userInterface.getTargetedPlayer(names);
                t = Main.pManager.getPlayerByName(target);
            }
                  enemyBoard e;
                  e = getEnemyBoardByName(t);
                  Main.userInterface.printEnemyBoard(e);

                  lastSeen = e;
                  
            if  (act == TurnManager.turnAction.MARK_ON_ENEMY_BOARD) {
                  int row = Main.userInterface.getSubmarineRow(0, Config.BOARD_START, Config.BOARD_START + Config.BOARD_SIZE);
                  int col = Main.userInterface.getSubmarineCol(0, Config.BOARD_START, Config.BOARD_START + Config.BOARD_SIZE);
                  if (!markOnBoard(Config.MARKED_SQUARE_SIGN, target, row, col))
                      Main.userInterface.printAlert("Could not mark on " + t.getName() + "'s board on coordinates " + (char)('A' + col + Config.BOARD_START) + "" + (row + (Config.BOARD_START+1)));
            } else if (act == TurnManager.turnAction.UNMARK_ON_ENEMY_BOARD) {
                  int row = Main.userInterface.getSubmarineRow(0, Config.BOARD_START, Config.BOARD_START + Config.BOARD_SIZE);
                  int col = Main.userInterface.getSubmarineCol(0, Config.BOARD_START, Config.BOARD_START + Config.BOARD_SIZE);
                  if (!markOnBoard(Config.EMPTY_SQUARE_SIGN, target, row, col))
                      Main.userInterface.printAlert("Could not unmark on " + t.getName() + "'s board on coordinates " + (char)('A' + col + Config.BOARD_START) + "" + (row + (Config.BOARD_START+1)));
            } else if (act == TurnManager.turnAction.VIEW_ENEMY_BOARD) { 
            } else if (act == TurnManager.turnAction.SEND_TORPEDO) {
                
                
                  int row = Main.userInterface.getSubmarineRow(0, Config.BOARD_START, Config.BOARD_START + Config.BOARD_SIZE);;
                  int col = Main.userInterface.getSubmarineCol(0, Config.BOARD_START, Config.BOARD_START + Config.BOARD_SIZE);
                  int hitResult;
                  
                  if (e.canBeTargeted(row, col)) 
                  {
                      hitResult = t.getTorpedo(row, col);
                      if (hitResult >= 0) {
                          //mark hit on the target board
                          Main.userInterface.printAlert("You've hit " + target);
                          markOnBoard(Config.HIT_SQUARE_SIGN, target, row, col);
                          NoticePlayerGotHit n = new NoticePlayerGotHit(t, Notice.NoticeType.PLAYER_GOT_HIT, row, col);
                          Main.nManager.spreadTheWord(this, t, n);

                          if (hitResult > 0) {
                              NoticePlayerSubmarineSunk sunk = new NoticePlayerSubmarineSunk(t, Notice.NoticeType.PLAYER_SUBMARINE_SUNK, hitResult);
                              Main.nManager.spreadTheWord(this, t, sunk);
                          }

                          if (t.isDead()) {
                              NoticePlayerQuit q = new NoticePlayerQuit(t, Notice.NoticeType.PLAYER_QUIT);
                              Main.pManager.playerQuit(t);
                              Main.nManager.spreadTheWord(this, this, q);
                              if (Main.pManager.numPlayersLeft() == 1) {
                                  played = true;
                              }
                          }
                      } else {
                          markOnBoard(Config.MISSED_SQUARE_SIGN, target, row, col);
                          Main.userInterface.printAlert("You've missed");
                          NoticePlayerGotLucky n = new NoticePlayerGotLucky(t, Notice.NoticeType.PLAYER_GOT_LUCKY, row, col);
                          Main.nManager.spreadTheWord(this, t, n);
                          played = true;
                      }
                      e = getEnemyBoardByName(t);
                  } else {
                      Main.userInterface.printAlert("You cannot attack  " + t.getName() + " on coordinates " + (char)('A' + col + Config.BOARD_START) + "" + ((row + Config.BOARD_START+1)));
                  }
            } else {
                Main.userInterface.printAlert("Invalid options, Please try again");
            }
        }
        return false;        
    }

    public boolean playTurn(TurnManager.turnAction act, String targetPlayer, int row, int col) { //use for web
        readNotices();
        //TurnManager.turnAction act;
        boolean played = false;
        Player t = null;
        String target = "";
        
        while (!played) {
            Main.userInterface.printBoard(lastSeen);
            //act = Main.userInterface.getPlayersNextMove();
            
            if (act == TurnManager.turnAction.QUIT_GAME)
                return true;
            
            LinkedList<String> names = new LinkedList<String>();
            for (int i = 0; i < Main.pManager.numPlayersLeft(); i++) {
                Player tmp = Main.pManager.getNextPlayer();
                if (!tmp.getName().equals(getName())) {
                    names.add(tmp.getName());
                }
            }

            if (Main.pManager.numPlayersLeft() == 2) {
                Player tmp = Main.pManager.getNextPlayer();
                target = tmp.getName();
                tmp = Main.pManager.getNextPlayer();
                t = Main.pManager.getPlayerByName(target);
            } else {
                //target = Main.userInterface.getTargetedPlayer(names);
                target = targetPlayer;
                t = Main.pManager.getPlayerByName(target);
            }
                  enemyBoard e;
                  e = getEnemyBoardByName(t);
                  Main.userInterface.printEnemyBoard(e);

                  lastSeen = e;
                  
            if  (act == TurnManager.turnAction.MARK_ON_ENEMY_BOARD) {
                  //int row = Main.userInterface.getSubmarineRow(0, Config.BOARD_START, Config.BOARD_START + Config.BOARD_SIZE);
                  //int col = Main.userInterface.getSubmarineCol(0, Config.BOARD_START, Config.BOARD_START + Config.BOARD_SIZE);
                  if (!markOnBoard(Config.MARKED_SQUARE_SIGN, target, row, col))
                      Main.userInterface.printAlert("Could not mark on " + t.getName() + "'s board on coordinates " + (char)('A' + col + Config.BOARD_START) + "" + (row + (Config.BOARD_START+1)));
            } else if (act == TurnManager.turnAction.UNMARK_ON_ENEMY_BOARD) {
                  //int row = Main.userInterface.getSubmarineRow(0, Config.BOARD_START, Config.BOARD_START + Config.BOARD_SIZE);
                  //int col = Main.userInterface.getSubmarineCol(0, Config.BOARD_START, Config.BOARD_START + Config.BOARD_SIZE);
                  if (!markOnBoard(Config.EMPTY_SQUARE_SIGN, target, row, col))
                      Main.userInterface.printAlert("Could not unmark on " + t.getName() + "'s board on coordinates " + (char)('A' + col + Config.BOARD_START) + "" + (row + (Config.BOARD_START+1)));
            } else if (act == TurnManager.turnAction.VIEW_ENEMY_BOARD) { 
            } else if (act == TurnManager.turnAction.SEND_TORPEDO) {
                
                
                  //int row = Main.userInterface.getSubmarineRow(0, Config.BOARD_START, Config.BOARD_START + Config.BOARD_SIZE);;
                  //int col = Main.userInterface.getSubmarineCol(0, Config.BOARD_START, Config.BOARD_START + Config.BOARD_SIZE);
                  int hitResult;
                  
                  if (e.canBeTargeted(row, col)) 
                  {
                      hitResult = t.getTorpedo(row, col);
                      if (hitResult >= 0) {
                          //mark hit on the target board
                          Main.userInterface.printAlert("You've hit " + target);
                          markOnBoard(Config.HIT_SQUARE_SIGN, target, row, col);
                          NoticePlayerGotHit n = new NoticePlayerGotHit(t, Notice.NoticeType.PLAYER_GOT_HIT, row, col);
                          Main.nManager.spreadTheWord(this, t, n);

                          if (hitResult > 0) {
                              NoticePlayerSubmarineSunk sunk = new NoticePlayerSubmarineSunk(t, Notice.NoticeType.PLAYER_SUBMARINE_SUNK, hitResult);
                              Main.nManager.spreadTheWord(this, t, sunk);
                          }

                          if (t.isDead()) {
                              NoticePlayerQuit q = new NoticePlayerQuit(t, Notice.NoticeType.PLAYER_QUIT);
                              Main.pManager.playerQuit(t);
                              Main.nManager.spreadTheWord(this, this, q);
                              if (Main.pManager.numPlayersLeft() == 1) {
                                  played = true;
                              }
                          }
                      } else {
                          markOnBoard(Config.MISSED_SQUARE_SIGN, target, row, col);
                          Main.userInterface.printAlert("You've missed");
                          NoticePlayerGotLucky n = new NoticePlayerGotLucky(t, Notice.NoticeType.PLAYER_GOT_LUCKY, row, col);
                          Main.nManager.spreadTheWord(this, t, n);
                          played = true;
                      }
                      e = getEnemyBoardByName(t);
                  } else {
                      Main.userInterface.printAlert("You cannot attack  " + t.getName() + " on coordinates " + (char)('A' + col + Config.BOARD_START) + "" + ((row + Config.BOARD_START+1)));
                  }
            } else {
                Main.userInterface.printAlert("Invalid options, Please try again");
            }
        }
        return false;        
    }
}